package com.dag.eagleshop.core.account.service.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.dag.eagleshop.core.account.model.dto.account.*;
import com.dag.eagleshop.core.account.model.dto.base.IdDTO;
import com.dag.eagleshop.core.account.model.dto.base.IdsDTO;
import com.dag.eagleshop.core.account.model.dto.base.PageDTO;
import com.dag.eagleshop.core.account.model.dto.base.ViewPage;
import com.dag.eagleshop.core.account.model.dto.member.MemberDTO;
import com.dag.eagleshop.core.account.model.dto.member.OpenMemberDTO;
import com.dag.eagleshop.core.account.model.dto.payment.PaymentRecordDTO;
import com.dag.eagleshop.core.account.model.dto.payment.RefundRecordDTO;
import com.dag.eagleshop.core.account.model.dto.withdraw.*;
import com.dag.eagleshop.core.account.model.enums.*;
import com.dag.eagleshop.core.account.service.AccountManager;
import com.dag.eagleshop.core.account.utils.HttpUtils;
import com.enation.app.javashop.core.member.model.dos.Member;
import com.enation.app.javashop.core.member.service.MemberManager;
import com.enation.app.javashop.core.payment.model.enums.TransferCodeEnum;
import com.enation.app.javashop.core.payment.model.vo.TransferBill;
import com.enation.app.javashop.core.payment.service.WechatSmallchangeManager;
import com.enation.app.javashop.core.system.sendMessage.WechatSendMessage;
import com.enation.app.javashop.framework.exception.ServiceException;
import com.enation.app.javashop.framework.logs.Logger;
import com.enation.app.javashop.framework.util.BeanUtil;
import com.enation.app.javashop.framework.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;

/**
 * 账户服务
 */
@Slf4j
@Service
public class AccountManagerImpl implements AccountManager {

    @Value("${service.account.url}")
    private String url;
    @Autowired
    private WechatSmallchangeManager wechatSmallchangeManager;
    @Autowired
    private MemberManager memberManager;
    @Autowired
    private WechatSendMessage wechatSendMessage;

    /**
     * 开通会员
     */
    @Override
    public MemberDTO openMember(OpenMemberDTO openMemberDTO) {
        String requestPath = url + AccountConstants.OPEN_MEMBER;
        return HttpUtils.httpPostByJson(requestPath, openMemberDTO, MemberDTO.class);
    }

    /**
     * 根据会员id查询账户会员
     */
    @Override
    public MemberDTO queryMemberById(String memberId) {
        String requestPath = url + AccountConstants.QUERY_BY_ID;
        return HttpUtils.httpPostByJson(requestPath, IdDTO.by(memberId), MemberDTO.class);
    }

    /**
     * 根据会员和账户类型查询账户
     */
    @Override
    public AccountDTO queryByMemberIdAndAccountType(String memberId, Integer accountType) {
        String requestPath = url + AccountConstants.QUERY_BY_MEMBER_ID_AND_ACCOUNT_TYPE + "?memberId=" + memberId + "&accountType=" + accountType;
        return HttpUtils.httpGetByJson(requestPath, AccountDTO.class);
    }


    /**
     * 开通账户
     */
    @Override
    public AccountDTO openAccount(OpenAccountDTO openAccountDTO) {
        String requestPath = url + AccountConstants.OPEN_ACCOUNT;
        return HttpUtils.httpPostByJson(requestPath, openAccountDTO, AccountDTO.class);
    }

    /**
     * 账户统计
     *
     * @param memberId 虚拟账户memberId
     *                 就是accountMemberId
     */
    @Override
    public CountAccountDTO summary(String memberId) {
        String requestPath = url + AccountConstants.SUMMARY + "?memberId=" + memberId;
        return HttpUtils.httpGetByJson(requestPath, CountAccountDTO.class);
    }


    /**
     * 转账
     */
    @Override
    public TransferRespDTO transfer(TransferReqDTO transferReqDTO) {
        String requestPath = url + AccountConstants.TRANSFER;
        return HttpUtils.httpPostByJson(requestPath, transferReqDTO, TransferRespDTO.class);
    }


    /**
     * 业务转账
     */
    @Override
    public BusinessTransferRespDTO businessTransfer(BusinessTransferReqDTO transferReqDTO) {
        String tradeVoucherNo = transferReqDTO.getTradeVoucherNo();
        List<TransferReqDTO> transferReqList = transferReqDTO.getTransferReqList();
        for (int i = 0; i < transferReqList.size(); i++) {
            TransferReqDTO reqDTO = transferReqList.get(i);
            reqDTO.setTradeVoucherNo(tradeVoucherNo + i);
            reqDTO.setOperatorId(transferReqDTO.getOperatorId());
            reqDTO.setOperatorName(transferReqDTO.getOperatorName());
        }
        String requestPath = url + AccountConstants.BUSINESS_TRANSFER;
        return HttpUtils.httpPostByJson(requestPath, transferReqDTO, BusinessTransferRespDTO.class);
    }

    /**
     * 查询提现记录
     */
    @Override
    public ViewPage<WithdrawBillDTO> queryWithdrawList(PageDTO<QueryWithdrawBillDTO> pageDTO) {
        String requestPath = url + AccountConstants.QUERY_WITHDRAW_LIST;
        return HttpUtils.httpPostByJson(requestPath, pageDTO, ViewPage.class);
    }

    @Override
    public List<WithdrawBill> queryListByIds(IdsDTO<String> idsDTO) {
        String requestPath = url + AccountConstants.QUERY_LIST_BY_IDS;
        return HttpUtils.httpPostByJson(requestPath, idsDTO, List.class);
    }

    /**
     * 申请提现
     */
    @Override
    public ApplyWithdrawRespDTO applyWithdraw(ApplyWithdrawReqDTO applyWithdrawReqDTO) {
        String requestPath = url + AccountConstants.APPLY_WITHDRAW;
        return HttpUtils.httpPostByJson(requestPath, applyWithdrawReqDTO, ApplyWithdrawRespDTO.class);
    }

    /**
     * 审核
     */
    @Override
    public boolean auditing(AuditingDTO auditingDTO) {
        String requestPath = url + AccountConstants.AUDITING;
        return HttpUtils.httpPostByJson(requestPath, auditingDTO, Boolean.class);
    }

    /**
     * 标记转账
     */
    @Override
    public MarkTransferredDTO markTransfer(MarkTransferredDTO markTransferredDTO) {

        //1、查询提现单
        QueryWithdrawBillDTO queryWithdrawBillDTO = new QueryWithdrawBillDTO();
        queryWithdrawBillDTO.setId(markTransferredDTO.getWithdrawBillId());
        ViewPage<WithdrawBillDTO> withdrawBillDTOViewPage = this.queryWithdrawList(new PageDTO(1, 1, queryWithdrawBillDTO));
        List<WithdrawBillDTO> withdrawBillDTOList = withdrawBillDTOViewPage.getRecords();
        if (!CollectionUtils.isEmpty(withdrawBillDTOList)) {
            WithdrawBillDTO withdrawBillDTO = JSON.parseObject(JSON.toJSON(withdrawBillDTOList.get(0)).toString(), new TypeReference<WithdrawBillDTO>() {
            });
            //2、线上付款，且提现渠道为微信时，调用接口走实际的微信转账流程
            if (withdrawBillDTO.getWithdrawType() == WithdrawTypeEnum.ONLINE.getIndex() && withdrawBillDTO.getWithdrawChannel() == TradeChannelEnum.WECHAT.getIndex()) {
                TransferBill transferBill = new TransferBill();
                transferBill.setPartnerTradeNo(withdrawBillDTO.getWithdrawNo());
                transferBill.setTransferPrice(withdrawBillDTO.getAmount().doubleValue());
                transferBill.setDescribe("智溢商城钱包提现");
                Member member = memberManager.getMemberByAccountMemberId(withdrawBillDTO.getMemberId());
                transferBill.setPayeeMemberId(member.getMemberId());
                transferBill.setRealName(withdrawBillDTO.getOtherAccountName());
                log.info("开始调用微信接口 wechatSmallchangeManager.transfer：" + JSON.toJSON(markTransferredDTO).toString());
                Map<String, String> resultMap = wechatSmallchangeManager.transfer(transferBill);
                markTransferredDTO.setStatus(Integer.parseInt(resultMap.get("withdrawStatus")));
                markTransferredDTO.setTransferRemark(resultMap.get("sendMessage"));
                markTransferredDTO.setRealFailReason(resultMap.get("alertMessage"));
            } else if (markTransferredDTO.getStatus() == null) {
                // 如果不是线上打款，且前端没有传转账状态，则默认线下转账成功
                markTransferredDTO.setStatus(WithdrawStatusEnum.SUCCESS.getIndex());
            }
            // 3、标记为转账
            String requestPath = url + AccountConstants.MARK_TRANSFERRED;
            HttpUtils.httpPostByJson(requestPath, markTransferredDTO, Boolean.class);
        } else {
            //没有查询到提现单
            throw new ServiceException("500", "没有查询到提现单");
        }
        return markTransferredDTO;
    }

    //查询并更新微信转账状态
    @Override
    public void updateTransferStatus() {
        //1、查询支付中的提现单
        QueryWithdrawBillDTO queryWithdrawBillDTO = new QueryWithdrawBillDTO();
        queryWithdrawBillDTO.setStatus(WithdrawStatusEnum.PAY_UNDERWAY.getIndex());
        ViewPage<WithdrawBillDTO> withdrawBillDTOViewPage = this.queryWithdrawList(new PageDTO(1, 100, queryWithdrawBillDTO));
        List<WithdrawBillDTO> withdrawBillDTOList = withdrawBillDTOViewPage.getRecords();
        if (!CollectionUtils.isEmpty(withdrawBillDTOList)) {
            for (int i = 0; i < withdrawBillDTOList.size(); i++) {
                WithdrawBillDTO withdrawBillDTO = JSON.parseObject(JSON.toJSON(withdrawBillDTOList.get(i)).toString(), new TypeReference<WithdrawBillDTO>() {
                });
                //2、调用微信接口查询提现单是否转账成功
                Map<String, String> resultMap = wechatSmallchangeManager.gettransferinfo(withdrawBillDTO.getWithdrawNo());
                //微信转账状态
                Integer tranferStatus = Integer.parseInt(resultMap.get("tranferStatus"));
                //转账失败原因
                String fialReason = resultMap.get("fialReason");

                //3、只有提现成功或提现失败才会修改提现单和交易单状态
                if (tranferStatus == WithdrawStatusEnum.SUCCESS.getIndex() || tranferStatus == WithdrawStatusEnum.FAIL.getIndex()) {
                    //修改交易单和提现单的状态
                    String requestPath = url + AccountConstants.MARK_TRANSFERRED;
                    MarkTransferredDTO markTransferredDTO = new MarkTransferredDTO();
                    markTransferredDTO.setWithdrawBillId(withdrawBillDTO.getId());
                    markTransferredDTO.setOperatorId(withdrawBillDTO.getUpdaterId());
                    String tranferRemark = StringUtil.isEmpty(fialReason) ? withdrawBillDTO.getTransferRemark() : fialReason;
                    markTransferredDTO.setTransferRemark(tranferRemark);
                    markTransferredDTO.setStatus(tranferStatus);
                    markTransferredDTO.setOperatorName("平台");
                    HttpUtils.httpPostByJson(requestPath, markTransferredDTO, Boolean.class);

                    //提现成功就发送消息
                    if (markTransferredDTO.getStatus() == WithdrawStatusEnum.SUCCESS.getIndex()) {
                        wechatSendMessage.sendMarkTransferMessage(markTransferredDTO);
                    } else if (WithdrawStatusEnum.FAIL.getIndex() == tranferStatus) {
                        // 提现失败，且失败原因为：没有绑定openId/真实姓名校验出错/微信没有实名认证才会发送转账失败的推送消息
                        if (tranferRemark.equals(TransferCodeEnum.E603.getDescription()) ||
                                tranferRemark.equals(TransferCodeEnum.E611.getDescription()) ||
                                tranferRemark.equals(TransferCodeEnum.E612.getDescription())) {
                            //微信转账接口异常，发推送
                            wechatSendMessage.sendMarkTransferMessage(markTransferredDTO);
                        }
                    }
                }
            }
        }
    }


    /**
     * 支付记录
     */
    @Override
    public boolean paymentRecord(PaymentRecordDTO paymentRecordDTO) {
        String requestPath = url + AccountConstants.PAYMENT_RECORD;
        return HttpUtils.httpPostByJson(requestPath, paymentRecordDTO, Boolean.class);
    }

    /**
     * 退款记录
     */
    @Override
    public boolean refundRecord(RefundRecordDTO refundRecordDTO) {
        String requestPath = url + AccountConstants.REFUND_RECORD;
        return HttpUtils.httpPostByJson(requestPath, refundRecordDTO, Boolean.class);
    }

    /**
     * 查询交易记录列表
     */
    @Override
    public ViewPage<TradeRecordDTO> queryTradeRecordList(PageDTO<QueryTradeRecordDTO> pageDTO) {
        String requestPath = url + AccountConstants.QUERY_TRADE_RECORD_LIST;
        return HttpUtils.httpPostByJson(requestPath, pageDTO, ViewPage.class);
    }

    /**
     * 查询平台会员
     */
    @Override
    public MemberDTO queryPlatformMember() {
        String requestPath = url + AccountConstants.QUERY_PLATFORM_MEMBER;
        return HttpUtils.httpGetByJson(requestPath, MemberDTO.class);
    }

    /**
     * 查询平台账户
     */
    @Override
    public AccountDTO queryPlatformAccount(Integer accountType) {
        String requestPath = url + AccountConstants.QUERY_PLATFORM_ACCOUNT + "?accountType=" + accountType;
        return HttpUtils.httpGetByJson(requestPath, AccountDTO.class);
    }

    @Override
    public ViewPage<WithdrawAccountDTO> queryWithdrawAccountList(PageDTO<QueryWithdrawAccountDTO> pageDTO) {
        String requestPath = url + AccountConstants.QUERY_WITHDRAW_ACCOUNT_LIST;
        return HttpUtils.httpPostByJson(requestPath, pageDTO, ViewPage.class);
    }

    @Override
    public boolean addWithdrawAccount(AddWithdrawAccountDTO addWithdrawAccountDTO) {
        String requestPath = url + AccountConstants.ADD_WITHDRAW_ACCOUNT;
        return HttpUtils.httpPostByJson(requestPath, addWithdrawAccountDTO, Boolean.class);
    }

    @Override
    public boolean updateWithdrawAccountById(UpdateWithdrawAccountDTO updateWithdrawAccountDTO) {
        String requestPath = url + AccountConstants.UPDATE_WITHDRAW_ACCOUNT_BY_ID;
        return HttpUtils.httpPostByJson(requestPath, updateWithdrawAccountDTO, Boolean.class);
    }

    @Override
    public void delWithdrawAccountById(IdDTO<String> idDTO) {
        String requestPath = url + AccountConstants.DEL_WITHDRAW_ACCOUNT_BY_ID;
        HttpUtils.httpPostByJson(requestPath, idDTO, Void.class);
    }
}
